package com.gt.wxpay.cashier.payChannel.handler;

import com.gt.wxpay.cashier.common.LocalTimeUtils;
import com.gt.wxpay.cashier.common.RuleCommonUilt;
import com.gt.wxpay.cashier.domain.dto.QueryRefundDto;
import com.gt.wxpay.cashier.domain.model.CashierPayment;
import com.gt.wxpay.cashier.domain.model.PayTypeEnum;
import com.gt.wxpay.cashier.domain.model.PaymentStatusEnum;
import com.gt.wxpay.cashier.payChannel.application.WxConfigService;
import com.gt.wxpay.cashier.payChannel.callback.vo.WxPayRespDto;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.Refund;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * packageName com.gt.wxpay.cashier.payChannel.handler
 *
 * @author GuoTong
 * @version JDK 8
 * @className OperationWxHandler
 * @date 2024/3/16
 * @description 微信支付实现接口--底层调用SDK
 */
@Component
public class OperationWxHandler {
    private Logger logger = LoggerFactory.getLogger(OperationWxHandler.class);
    @Autowired
    private JsapiPrepayHandler jsapiPrepayHandler;

    @Autowired
    private NativePrepayHandler nativePrepayHandler;

    @Autowired
    private WxConfigService wxConfigService;

    /**
     * 调用微信支付下单的接口
     *
     * @param cashierPayment 订单实例
     * @return
     */
    public WxPayRespDto handlePrepay(CashierPayment cashierPayment) {
        // 根据下单方式 调用不同的下单接口
        switch (cashierPayment.getChannelPayType()) {
            case RuleCommonUilt.WX_JSAPI:
                return jsapiPrepayHandler.handlePrepay(cashierPayment);
            case RuleCommonUilt.WX_NATIVE:
                return nativePrepayHandler.handlePrepay(cashierPayment);
            case RuleCommonUilt.WX_APP:
                return appOrder(cashierPayment);
            case RuleCommonUilt.WX_MWEB:
                return mwebOrder(cashierPayment);
            default:
                throw new IllegalArgumentException(RuleCommonUilt.NOT_SUPPER_TYPE + cashierPayment.getChannelPayType());
        }
    }


    /**
     * 根基收银台的流水号查询微信侧的单子详情
     *
     * @param cashierPayment
     * @return
     */
    public CashierPayment queryOrderInfo(CashierPayment cashierPayment) {
        // 根据下单方式 调用不同的下单接口
        switch (cashierPayment.getChannelPayType()) {
            case RuleCommonUilt.WX_JSAPI:
                // 获取支付订单结果
                Transaction transaction = jsapiPrepayHandler.queryOrderInfo(cashierPayment);
                return handlerThisTransaction(transaction, cashierPayment);
            case RuleCommonUilt.WX_NATIVE:
                // 获取支付订单结果
                Transaction transactionNative = nativePrepayHandler.queryOrderInfo(cashierPayment);
                return handlerThisTransaction(transactionNative, cashierPayment);
            case RuleCommonUilt.WX_APP:
            case RuleCommonUilt.WX_MWEB:
            default:
                throw new IllegalArgumentException(RuleCommonUilt.NOT_SUPPER_TYPE + cashierPayment.getChannelPayType());
        }
    }

    /**
     * 【交易状态】 交易状态，枚举值：
     * * SUCCESS：支付成功
     * * REFUND：转入退款
     * * NOTPAY：未支付
     * * CLOSED：已关闭
     * * REVOKED：已撤销（仅付款码支付会返回）
     * * USERPAYING：用户支付中（仅付款码支付会返回）
     * * PAYERROR：支付失败（仅付款码支付会返回）
     */
    private CashierPayment handlerThisTransaction(Transaction transaction, CashierPayment cashierPayment) {
        Transaction.TradeStateEnum tradeState = transaction.getTradeState();
        switch (tradeState) {
            case SUCCESS:
                // 设置已支付
                cashierPayment.setStatus(PaymentStatusEnum.PAYED.code());
                String successTime = transaction.getSuccessTime();
                if (StringUtils.isNotBlank(successTime)) {
                    Date successDate = LocalTimeUtils.dealDateFormatWithWx(successTime);
                    cashierPayment.setSuccessTime(successDate);
                }
                break;
            case REFUND:
                cashierPayment.setStatus(PaymentStatusEnum.REFUNDING.code());
                break;
            case NOTPAY:
                cashierPayment.setStatus(PaymentStatusEnum.UNPAY.code());
                break;
            case CLOSED:
                cashierPayment.setStatus(PaymentStatusEnum.CLOSED.code());
                break;
            case REVOKED:
                cashierPayment.setStatus(PaymentStatusEnum.CANCELLED.code());
                break;
            case USERPAYING:
                cashierPayment.setStatus(PaymentStatusEnum.PAYING.code());
                break;
            case PAYERROR:
                cashierPayment.setStatus(PaymentStatusEnum.PAYERROR.code());
                break;
            default:
                break;
        }
        // 交易金额
        cashierPayment.setSuccessAmount(transaction.getAmount().getTotal().longValue());
        cashierPayment.setCurrencyType(transaction.getAmount().getCurrency());
        // 取微信返回的流水号
        cashierPayment.setChannelFlowNo(transaction.getTransactionId());
        // 更新支付渠道返回的流水号--由预下单流水号转化为支付流水号
        cashierPayment.setChannelReturnCode(tradeState.name());
        cashierPayment.setChannelReturnMessage(transaction.getTradeStateDesc());

        return cashierPayment;
    }


    private WxPayRespDto appOrder(CashierPayment cashierPayment) {
        throw new RuntimeException(RuleCommonUilt.NOT_SUPPER_TYPE + RuleCommonUilt.WX_APP);
    }

    public WxPayRespDto mwebOrder(CashierPayment payment) {
        throw new RuntimeException(RuleCommonUilt.NOT_SUPPER_TYPE + RuleCommonUilt.WX_MWEB);
    }

    public NotificationConfig getNotificationConfig(Long payChannelId) {
        return wxConfigService.getCallBackConfig(payChannelId);
    }

    public void closePayment(CashierPayment cashierPayment) {
        // 根据下单方式 调用不同的下单接口
        switch (cashierPayment.getChannelPayType()) {
            case RuleCommonUilt.WX_JSAPI:
                // 关闭订单
                jsapiPrepayHandler.closePayment(cashierPayment);
                return;
            case RuleCommonUilt.WX_NATIVE:
                // 关闭订单
                nativePrepayHandler.closePayment(cashierPayment);
                return;
            case RuleCommonUilt.WX_APP:
            case RuleCommonUilt.WX_MWEB:
            default:
                throw new IllegalArgumentException(RuleCommonUilt.NOT_SUPPER_TYPE + cashierPayment.getChannelPayType());
        }
    }

    public Refund refundOrderV3(CashierPayment cashierPayment) {
        // 根据退款方式 调用不同的退款下单接口
        switch (cashierPayment.getChannelPayType()) {
            case RuleCommonUilt.WX_JSAPI:
                // 获取退款订单结果
                return jsapiPrepayHandler.refundOrderV3(cashierPayment);
            case RuleCommonUilt.WX_NATIVE:
                // 获取退款订单结果
                return nativePrepayHandler.refundOrderV3(cashierPayment);
            case RuleCommonUilt.WX_APP:
            case RuleCommonUilt.WX_MWEB:
            default:
                throw new IllegalArgumentException(RuleCommonUilt.NOT_SUPPER_TYPE + cashierPayment.getChannelPayType());
        }
    }

    public QueryRefundDto queryRefund(CashierPayment refundOrder) {
        // 根据退款方式 调用不同的退款下单接口
        switch (refundOrder.getChannelPayType()) {
            case RuleCommonUilt.WX_JSAPI:
                // 获取退款订单结果
                return jsapiPrepayHandler.queryRefundOrderV3(refundOrder);
            case RuleCommonUilt.WX_NATIVE:
                // 获取退款订单结果
                return nativePrepayHandler.queryRefundOrderV3(refundOrder);
            case RuleCommonUilt.WX_APP:
            case RuleCommonUilt.WX_MWEB:
            default:
                throw new IllegalArgumentException(RuleCommonUilt.NOT_SUPPER_TYPE + refundOrder.getChannelPayType());
        }
    }

    public NotificationConfig getCallBackConfig(PayTypeEnum wechat) {
        return wxConfigService.getCallBackConfig(wechat);
    }
}
